﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using AutoLoL.Entities;
using AutoLoL.Logic.Masteries;
using AutoLoL.Logic.Repositories;
using AutoLoL.Shared;
using AutoLoL.Logic.Factories;

namespace AutoLoL.Logic
{
    public class ChampionBuildRepository
    {
        public static ChampionBuild Create(Champion champion, IMasteryRepository masteryRepository)
        {
            ChampionBuild championBuild = new ChampionBuild();
            championBuild.Champion = champion;
            championBuild.Guide = Constants.DEFAULT_BUILD_GUIDE;
            championBuild.MasteryBuild = masteryRepository.GetMasteryBuild();

            return championBuild;
        }

        public static List<ChampionBuild> GetAll(IChampionRepository championRepository, IItemRepository itemRepository, ISummonerSpellRepository summonerSpellRepository, IMasteryRepository masteryRepository)
        {
            List<ChampionBuild> championBuilds = new List<ChampionBuild>();

            if (Directory.Exists(Constants.BUILDS_DIRECTORY))
            {
                string[] files = Directory.GetFiles(Constants.BUILDS_DIRECTORY, "*.xml");
                foreach (string file in files)
                {
                    try
                    {
                        XDocument doc = XDocument.Load(file);
                        ChampionBuild championBuild = FromXDocument(doc, championRepository, itemRepository, summonerSpellRepository, masteryRepository);
                        if (championBuild != null)
                        {
                            championBuilds.Add(championBuild);
                        }
                    }
                    catch { if (Debugger.IsAttached) throw; }
                }
            }

            return championBuilds;
        }

        public static void Save(ChampionBuild championBuild)
        {
            if (championBuild.ChampionBuildId == null || championBuild.ChampionBuildId == Guid.Empty)
            {
                championBuild.ChampionBuildId = Guid.NewGuid();
            }

            string fileName = System.IO.Path.Combine(Constants.BUILDS_DIRECTORY, championBuild.ChampionBuildId.ToString() + ".xml");

            XDocument doc = new XDocument();
            XElement root = new XElement("build");
            root.Add(new XElement("id", championBuild.ChampionBuildId.ToString()));
            root.Add(new XElement("title", championBuild.Title));
            root.Add(new XElement("champion", championBuild.Champion.Name));
            root.Add(new XElement("masteries", championBuild.MasteryBuild));
            root.Add(new XElement("gametype", championBuild.GameType));

            XElement items = new XElement("items");
            for (int i = 0; i < championBuild.Items.Length; i++)
            {
                int id = 0;
                if (championBuild.Items[i] != null)
                {
                    id = championBuild.Items[i].ItemId;
                }

                items.Add(new XElement("item", id));
            }

            root.Add(items);

            XElement spells = new XElement("spells");
            for (int i = 0; i < championBuild.SummonerSpells.Length; i++)
            {
                string spell = string.Empty;
                if (championBuild.SummonerSpells[i] != null)
                {
                    spell = championBuild.SummonerSpells[i].Name;
                }

                spells.Add(new XElement("spell", spell));
            }

            root.Add(spells);

            root.Add(new XElement("guide", championBuild.Guide));

            doc.Add(root);

            if (!Directory.Exists(Constants.BUILDS_DIRECTORY))
            {
                Directory.CreateDirectory(Constants.BUILDS_DIRECTORY);
            }

            doc.Save(fileName);
        }

        private static ChampionBuild FromXDocument(XDocument doc, IChampionRepository championRepository, IItemRepository itemRepository, ISummonerSpellRepository summonerSpellRepository, IMasteryRepository masteryRepository)
        {
            try
            {
                int index;
                ChampionBuild championBuild = new ChampionBuild();

                Guid id = new Guid(doc.Root.Element("id").Value);
                string title = doc.Root.Element("title").Value;
                Champion champion = championRepository.GetByName(doc.Root.Element("champion").Value);
                string masteryString = doc.Root.Element("masteries").Value;
                GameType gameType = GameType.Classic;
                if (doc.Root.Element("gametype") != null)
                {
                    gameType = (GameType)Enum.Parse(typeof(GameType), doc.Root.Element("gametype").Value);
                }

                index = 0;
                Item[] items = new Item[championBuild.Items.Length];
                foreach (XElement itemElement in doc.Root.Element("items").Elements("item"))
                {
                    items[index] = itemRepository.GetByItemId(int.Parse(itemElement.Value));
                    index++;
                }

                index = 0;
                SummonerSpell[] summonerSpells = new SummonerSpell[championBuild.SummonerSpells.Length];
                foreach (XElement summonerSpellElement in doc.Root.Element("spells").Elements("spell"))
                {
                    summonerSpells[index] = summonerSpellRepository.GetByName(summonerSpellElement.Value, masteryRepository);
                    index++;
                }

                string guide = doc.Root.Element("guide").Value;

                MasteryBuild masteryBuild = masteryRepository.GetMasteryBuild();
                MasteryBuildManager manager = new MasteryBuildManager(masteryBuild, MasteryFactory.Instance, SummonerSpellFactory.Instance);
                manager.FromString(masteryString);

                if (champion != null)
                {
                    championBuild.ChampionBuildId = id;
                    championBuild.Title = title;
                    championBuild.Champion = champion;
                    championBuild.MasteryBuild = masteryBuild;
                    championBuild.GameType = gameType;
                    championBuild.Items = items;
                    championBuild.SummonerSpells = summonerSpells;
                    championBuild.Guide = guide;
                    return championBuild;
                }
            }
            catch { if (Debugger.IsAttached) throw; }

            return null;
        }

        public static void Delete(ChampionBuild championBuild)
        {
            string fileName = System.IO.Path.Combine(Constants.BUILDS_DIRECTORY, championBuild.ChampionBuildId.ToString() + ".xml");
            if (File.Exists(fileName))
            {
                File.Delete(fileName);
            }
        }
    }
}
